<?php
/**
 * Created by PhpStorm.
 * User: caoyangmin
 * Date: 16/11/13
 * Time: 下午11:18
 */

namespace Once\Annotations\Controller;

namespace Once\Annotations\Controller;
use Once\Annotations\BaseAnnotationHandler;
use Once\Container\ControllerContainer;
use Once\Exceptions\AnnotationSyntaxExceptions;
use Once\Metas\ReturnMeta;
use Once\Utils\ObjectAccess;
use Once\Utils\TypeHint;
use Once\Utils\Verify;

class AnnBind extends BaseAnnotationHandler
{
    public function __construct(ControllerContainer $container, BaseAnnotationHandler $parent=null){
        $this->container = $container;
        $this->parent = $parent;
    }

    /**
     * @param $target
     * @param $name
     * @param $value
     * @return bool
     */
    protected function handleMethod($target, $name, $value)
    {
        $route = $this->container->getRoute($target);
        if(!$route) {
            return false;
        }
        if ($this->parent ==null){
            \Once\Utils\Logger::warnging("@$name should be used with a parent annotation");
            return false;
        }
        $params = $this->getParams($value, 2);
        count($params)>0 or Verify::fail(new AnnotationSyntaxExceptions("something wrong with @o-bind $value"));

        ObjectAccess::isValidPath($params[0]) or Verify::fail(new AnnotationSyntaxExceptions("something wrong with @o-bind $value"));

        $doc = count($params)>1?$params[1]:'';

        $returnHandler = $route
            ->getActionInvoker()
            ->getReturnHandler();

        if ($this->parent instanceof AnnReturn){
            foreach ($returnHandler->getMappings() as $maping){
                if($maping->source == '$.return'){
                    $maping->doc = $doc;
                }
            }
            return true;
        }elseif($this->parent instanceof AnnParam){
            $paramMeta = $route->getActionInvoker()->getParamsBuilder()->getParam($this->parent->paramName);
            if($paramMeta->isPassedByReference){
                //输出绑定
                $returnHandler->setMapping($params[0], new ReturnMeta(
                    '$.params.'.$paramMeta->name, $paramMeta->type, $doc));
            }else{
                $paramMeta->source = $params[0];
            }
            return true;
        }
        \Once\Utils\Logger::warnging("@o-bind not work with parent ".get_class($this->parent));
        return false;
    }

    /**
     * @var ControllerContainer
     */
    private $container;

    /**
     * @var BaseAnnotationHandler
     */
    private $parent;
}